#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
网页截图并推送到企业微信群
"""

import requests
import base64
import hashlib
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By


class WebPageToWeChat:
    def __init__(self, webhook_url):
        """
        初始化
        :param webhook_url: 企业微信机器人的webhook地址
        """
        self.webhook_url = webhook_url
    
    def capture_webpage(self, url, output_path='screenshot.png', width=1200, height=1080, wait_time=10, full_page=True):
        """
        截取网页为图片
        :param url: 要截图的网页URL
        :param output_path: 保存截图的路径
        :param width: 浏览器窗口宽度
        :param height: 浏览器窗口高度
        :param wait_time: 等待时间（秒），用于等待chart.js加载
        :param full_page: 是否截取整个页面（包括需要滚动的部分）
        :return: 截图文件路径
        """
        # 配置Chrome选项
        chrome_options = Options()
        chrome_options.add_argument('--headless')  # 无头模式
        chrome_options.add_argument('--no-sandbox')
        chrome_options.add_argument('--disable-dev-shm-usage')
        chrome_options.add_argument(f'--window-size={width},{height}')
        chrome_options.add_argument('--disable-gpu')
        chrome_options.add_argument('--disable-blink-features=AutomationControlled')
        chrome_options.add_argument('--hide-scrollbars')  # 隐藏滚动条
        
        # 创建浏览器实例
        driver = webdriver.Chrome(options=chrome_options)
        
        try:
            print(f"正在访问: {url}")
            # 访问网页
            driver.get(url)
            
            # 等待页面基本加载完成
            driver.implicitly_wait(5)
            
            # 等待chart.js加载完成 - 检查canvas元素是否存在
            try:
                print("等待图表加载...")
                WebDriverWait(driver, 15).until(
                    EC.presence_of_element_located((By.TAG_NAME, "canvas"))
                )
                print("检测到canvas元素")
            except:
                print("未检测到canvas元素，继续等待...")
            
            # 额外等待时间，确保图表渲染完成
            print(f"等待 {wait_time} 秒以确保图表完全渲染...")
            time.sleep(wait_time)
            
            # 执行JavaScript检查是否还有"正在加载"的文本
            try:
                loading_text = driver.execute_script(
                    "return document.body.innerText.includes('正在加载');"
                )
                if loading_text:
                    print("检测到'正在加载'文本，再等待5秒...")
                    time.sleep(5)
            except:
                pass
            
            if full_page:
                # 先滚动页面，触发所有懒加载的图表
                print("开始滚动页面，触发所有图表加载...")
                
                # 获取页面总高度
                total_height = driver.execute_script("return document.body.scrollHeight")
                print(f"页面总高度: {total_height}px")
                
                # 分段滚动，确保所有内容都被触发加载
                viewport_height = driver.execute_script("return window.innerHeight")
                current_position = 0
                
                while current_position < total_height:
                    # 滚动到当前位置
                    driver.execute_script(f"window.scrollTo(0, {current_position});")
                    print(f"滚动到: {current_position}px")
                    time.sleep(2)  # 等待该区域的图表加载
                    
                    current_position += viewport_height
                
                # 滚动到底部
                driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
                print("已滚动到页面底部")
                time.sleep(3)
                
                # 重新获取页面高度（可能在滚动后有变化）
                total_height = driver.execute_script("return Math.max(document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight);")
                print(f"重新获取页面高度: {total_height}px")
                
                # 滚回顶部
                driver.execute_script("window.scrollTo(0, 0);")
                print("滚回顶部")
                time.sleep(2)
                
                # 增加额外高度余量（防止底部被截断）
                extra_height = 200
                final_height = total_height + extra_height
                print(f"调整窗口大小为: {width} x {final_height} (增加{extra_height}px余量)")
                driver.set_window_size(width, final_height)
                time.sleep(3)
                
                # 触发resize事件
                driver.execute_script("window.dispatchEvent(new Event('resize'));")
                
                # 等待图表重新渲染
                print(f"等待 {wait_time} 秒让图表重新渲染...")
                time.sleep(wait_time)
            
            # 截图
            driver.save_screenshot(output_path)
            print(f"✓ 截图已保存到: {output_path}")
            
            return output_path
        
        finally:
            driver.quit()
    
    def upload_image_to_wechat(self, image_path):
        """
        上传图片到企业微信，获取media_id
        :param image_path: 图片路径
        :return: media_id
        """
        # 读取图片
        with open(image_path, 'rb') as f:
            image_data = f.read()
        
        # 计算图片的md5
        md5 = hashlib.md5(image_data).hexdigest()
        
        # 转换为base64
        base64_data = base64.b64encode(image_data).decode('utf-8')
        
        return base64_data, md5
    
    def send_image_to_wechat(self, image_path):
        """
        发送图片到企业微信群
        :param image_path: 图片路径
        """
        # 获取图片的base64和md5
        base64_data, md5_hash = self.upload_image_to_wechat(image_path)
        
        # 构造消息体
        data = {
            "msgtype": "image",
            "image": {
                "base64": base64_data,
                "md5": md5_hash
            }
        }
        
        # 发送请求
        response = requests.post(self.webhook_url, json=data)
        
        if response.status_code == 200:
            result = response.json()
            if result.get('errcode') == 0:
                print("图片发送成功！")
            else:
                print(f"发送失败: {result.get('errmsg')}")
        else:
            print(f"请求失败，状态码: {response.status_code}")
        
        return response.json()


def main():
    # 配置参数
    WEBHOOK_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=36fbd2fa-3796-43a4-b8dc-b953faf08645"
    TARGET_URL = "http://devops.derucci.smart/outside/agents/reportView"
    
    # 创建实例
    bot = WebPageToWeChat(WEBHOOK_URL)
    
    # 截取网页 - 等待15秒让chart.js完全加载，full_page=True截取整个页面
    screenshot_path = bot.capture_webpage(TARGET_URL, wait_time=15, full_page=True)
    
    print(f"\n截图文件: {screenshot_path}")
    
    # 发送到企业微信
    bot.send_image_to_wechat(screenshot_path)


if __name__ == "__main__":
    main()
